﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using AOPDemo.Domain;
using AOPDemo.Interfaces;
using AOPDemo.Messages;
using AOPDemo.Services;
using PostSharp.Aspects;

namespace AOPDemo.Aspects
{
    [Serializable]
    public class Audit : OnMethodBoundaryAspect
    {
        [NonSerialized] private IAuditService auditService;

        private static bool HasSession(IEnumerable<object> arguments, out AuthToken authToken)
        {
            if (arguments.Any(argument => argument is ServiceRequest))
            {
                authToken =
                    arguments.Where(argument => argument is ServiceRequest).Cast<ServiceRequest>().First().AuthToken;
                return !string.IsNullOrEmpty(authToken.SessionId);
            }
            authToken = null;
            return false;
        }

        public override void RuntimeInitialize(MethodBase method)
        {
            auditService = new WebAuditService();
        }

        public override void OnEntry(MethodExecutionArgs args)
        {
            AuthToken authToken;
            if (HasSession(args.Arguments, out authToken))
                auditService.RecordTransaction(authToken, "Starting transaction: " + args.Method.Name);
        }

        public override void OnException(MethodExecutionArgs args)
        {
            AuthToken authToken;
            if (HasSession(args.Arguments, out authToken))
                auditService.RecordTransaction(authToken,
                                               "Exception occured while processing transaction: " + args.Method.Name);
        }

        public override void OnSuccess(MethodExecutionArgs args)
        {
            AuthToken authToken;
            if (HasSession(args.Arguments, out authToken))
                auditService.RecordTransaction(authToken,
                                               "Successfully finished processing transaction: " + args.Method.Name);
        }
    }
}